from flask import Blueprint, g, render_template, redirect, request
from .apis import Apis
import json
import os
import sys
import struct
import time
from socket import *
from . import calCrc
from . import crc
from .broker import Broker
from .flash import Flash
from .laser import Laser
from .dpin import DPin

from .canopus import Canopus
from .cdb import CDB
from openpyxl import load_workbook
import math
import binascii
import pandas as pd

# here define a route
download_bp = Blueprint(
    'download',
    '__name__',
)

a = Apis()
for_customer = a.is_for_customer()

def parse_ret(buffer_string):
    s1 = str(buffer_string)
    s2 = s1.split(">")
    s3 = s2[1].split('\\')
    buffer_string = s3[0]
    return buffer_string


# $0000;<*fw_ver>FW 1.0.1.20190730
def parse_cmdstr(buffer_string):
    s1 = str(buffer_string)
    s2 = s1.split(";")
    s3 = s2[0].split("'")
    buffer_string = s3[1]
    return buffer_string


@download_bp.route('/download')
def download():
    return render_template('download.html', title='Download', for_customer=for_customer)


@download_bp.route('/api/commit')
def commit():

    IP_ADDR = a.read_item_from_config_ini('dev', 'ip')
    s1 = socket()
    s1.connect((IP_ADDR, 1000))
    s1.recv(512)
    s1.send('*dl 2 5'.encode())
    buffer_string = s1.recv(512)
    if parse_cmdstr(buffer_string) == '$0000':
        return ("commit ok!")
    else:
        return ("commit failed!")


@download_bp.route('/api/verify_data')
def verify_data():
    b = Broker()
    dsp = Canopus(b)
    res = dsp.bin_verify()
    print(res)
    if 0x5a == res:
        return "CRC OK."
    else:
        return "CRC Error."


@download_bp.route('/api/transfer', methods=['GET', 'POST'])
def transfer():
    setdefaulttimeout(200000)
    IP_ADDR = a.read_item_from_config_ini('dev', 'ip')
    # PRODUCT = a.read_item_from_config_ini('dev', 'product')
    PRODUCT = a.get_product()

    print('PRODUCT: ' + PRODUCT)

    file_type = request.args.get('file_type')
    move_data_flag = int(request.args.get('move_data_flag'))
    print('++++++++++++++++++++++++++++++++++++++++++')
    print('move_data_flag: {}'.format(move_data_flag))
    print('++++++++++++++++++++++++++++++++++++++++++')
    file = request.files.get("dlfile")
    if file is None:
        return "error, file is null."

    print(file_type)
    if file_type == 'cmis_config_table':
        file_name = 'cmis.xlsx'
    else:
        file_name = file.filename

    print(file_name)
    file.save('./templates/files/' + file_name)

    if file_type == 'fpga':

        s1 = socket()
        s1.connect((IP_ADDR, 1000))
        s1.recv(512)

        # step1. erase flash
        # ------------------------------------------------------
        print("starting to erase flash ...")
        # s1.send('*dl 1 1'.encode())
        for i in range(0, 41):
            # addr = 65536 + i * 65536
            # FPGA Start address 0x400000 (4194304)
            addr = 4194304 + i * 65536
            print("erase addr: " + hex(addr))
            s1.send(('*flash -b ' + str(addr)).encode())
            buffer_string = s1.recv(512)
            time.sleep(0.5)

        s1.send('*dl 1 1'.encode())
        # print(parse_cmdstr(buffer_string))
        buffer_string = s1.recv(512)
        if parse_cmdstr(buffer_string) == '$0000':
            # if True:
            print('erase ok!')
            # step2 download fpga bin file
            # ------------------------------------------------------
            # s2 = socket(AF_INET, SOCK_STREAM)
            s2 = socket()
            s2.connect((IP_ADDR, 1080))
            # init_data = tcp_client_socket.recv(1024)
            # print(init_data.decode('gbk'))
            epoch = time.time()
            # f = open('osfp_evb_top_crc16.bin', 'rb')
            # f = open('osfp_evb_top_ver9c20_crc16.bin', 'rb')
            # f = open('demo_crc16.bin', 'rb')
            # f = open('test1_crc16_1.bin', 'rb')
            f = open('./templates/files/' + file_name, 'rb')
            block = 1
            try:
                while True:
                    chunk = f.read(256)
                    if not chunk:
                        break
                    # do_something_with(chunk)
                    print("block: #" + str(block) + "\tdownloading: " +
                          str(len(chunk)))
                    s2.send(chunk)
                    recv = s2.recv(1024)
                    print(recv.decode('gbk'))
                    block += 1
                    time.sleep(0.085)
            finally:
                f.close()

            s2.close()
            print('fpga download time: {:.3f} s'.format(time.time() - epoch))

            # step3. complete
            # ---------------------------------------------------------
            s1.send('*dl 1 2'.encode())
            buffer_string = s1.recv(512)
            if parse_cmdstr(buffer_string) == '$0000':
                print("fpga download complete.")
                # step4. verify
                # ------------------------------------------------------
                s1.send('*dl 1 3'.encode())
                buffer_string = s1.recv(512)
                if parse_cmdstr(buffer_string) == '$0000':
                    print("fpga verify ok.")
                    # step5. switch
                    # ---------------------------------------------------------
                    s1.send('*dl 1 4'.encode())
                    buffer_string = s1.recv(512)
                    if parse_cmdstr(buffer_string) == '$0000':
                        print("fpga switch ok!")
                    else:
                        print("fpga switch failed.")
                    # print("fpga switch skipped, pls manual switch.")
                else:
                    print("fpga verify failed.")
            else:
                print('not complete')
        else:
            print('erase failed')

        return ('Download completely. ')

    if file_type == 'firmware':
        s1 = socket()
        s1.connect((IP_ADDR, 1000))
        s1.recv(512)

        # step1.
        # ---------------------------------------------------------
        print("firmware download start  ...")

        s1.send('*dl 2 1'.encode())
        # print(parse_cmdstr(buffer_string))
        buffer_string = s1.recv(512)
        if parse_cmdstr(buffer_string) == '$0000':
            # if True:
            print('start ok!')
            # step2 downloading file
            s2 = socket()
            s2.connect((IP_ADDR, 1080))
            epoch = time.time()
            f = open('./templates/files/' + file_name, 'rb')
            block = 1
            try:
                while True:
                    chunk = f.read(256)
                    if not chunk:
                        break
                    # do_something_with(chunk)
                    print("block: #" + str(block) + "\tdownloading: " +
                          str(len(chunk)))
                    s2.send(chunk)
                    recv = s2.recv(1024)
                    print(recv.decode('gbk'))
                    block += 1
                    time.sleep(0.085)
            finally:
                f.close()

            s2.close()
            print('firmware download time: {:.3f} s'.format(time.time() -
                                                            epoch))

            # step3. complete
            # ---------------------------------------------------------
            s1.send('*dl 2 2'.encode())
            buffer_string = s1.recv(512)
            if parse_cmdstr(buffer_string) == '$0000':
                print("firmware download complete.")
                # step4. verify
                # ------------------------------------------------------
                s1.send('*dl 2 3'.encode())
                buffer_string = s1.recv(512)
                if parse_cmdstr(buffer_string) == '$0000':
                    print("firmware verify ok.")
                    # step5. switch
                    # ------------------------------------------------------
                    s1.send('*dl 2 4'.encode())
                    buffer_string = s1.recv(512)
                    if parse_cmdstr(buffer_string) == '$0000':
                        print("firmware switch ok!")

                        # step6. commit
                        # ------------------------------------------------
                        # print("waiting 10s for restart ...")
                        # time.sleep(10)
                        # s1.send('*dl 2 5'.encode())
                        # buffer_string = s1.recv(512)
                        # if parse_cmdstr(buffer_string) == '$0000':
                        #     print("commit ok!")
                        # else:
                        #     print("commit failed!")
                    else:
                        print("firmware switch failed.")
                    # print("firmware switch skipped, pls manual switch.")
                else:
                    print("firmware verify failed.")
            else:
                print('not complete')
        else:
            print('start failed')
        return ('Firmware download completely. Please restart the GUI in a few seconds.')

    if file_type == 'dsp' or file_type == 'module_firmware':
        s1 = socket()
        s1.connect((IP_ADDR, 1000))
        s1.recv(512)

        if file_type == 'dsp':
            start_addr = 65536
            loop_count = 41
            os.system("clean.bat")
            # Start preprocess =================================================================
            # dsp_file = 'Canpus_flash_image_normal_v0_1_0_0_N.bin'
            # dsp_file = bin_file = sys.argv[1]
            dsp_file = './templates/files/' + file_name
            print('Origin File Name: %s' % dsp_file)

            # get version from dsp filename
            # filename = "flash_image_normal_v0_13_2_0_N.bin"  
            try:
                # v = file_name.lower().replace('flash_image_normal_v', '').replace('_n.bin', '').split('_')
                v = file_name.lower().split('_v')[1].split('_n')[0].split('_')
                ver = ''
                for i in v:
                    v_tmp = '{:02X}'.format(int(i))
                    ver = ver + v_tmp

                dsp_version = int('0x' + ver, 16)
            except:
                # flash_image_normal_v0_14_9_0_N.BIN
                # print('dsp filename is invalid! please rename like this: flash_image_normal_v<xx_xx_xx_xx>_N.bin')
                # return('DSP filename is INVALID! Please rename like this: flash_image_normal_vxx_xx_xx_xx_N.bin and try again.')
                print('dsp filename is invalid! Please rename like this: *_v[xx_xx_xx_xx]_N*')
                return('DSP filename is INVALID! Please rename like this: *_v[xx_xx_xx_xx]_N*')
                # dsp_version = 0

            # print('dsp_version ...')
            # print(ver)
            # print(dsp_version)
            # print(int(version, 16))

            # finally dsp bin file
            addition_dsp_file = dsp_file.split('.')[0] + "_tmp1.bin"
            addition_dsp_file_tmp1 = open(addition_dsp_file, 'ab')

            with open(dsp_file, 'rb') as dsp1:
                dsp_bin = dsp1.read()

            dsp_file_len = len(dsp_bin)
            print('Origin File Len: %d' % dsp_file_len)

            leftspace = dsp_file_len % 256

            if leftspace == 0:
                addition = 0
            else:
                addition = 256 - leftspace

            print('Additon Len: ' + str(addition))

            addition_dsp_file_tmp1.write(dsp_bin)

            if addition != 0:
                print('Add Addition ...')
                print(addition)
                f_str = '{:0' + str(addition * 2) + 'X}'
                dsp_file_len_4 = ''.join(f_str.format(0))
                addition_dsp_file_tmp1.write(bytearray.fromhex(dsp_file_len_4))

            addition_dsp_file_tmp1.close()

            # print(addition_dsp_file)
            crc_val = calCrc.main(addition_dsp_file)
            # print(hex(crc_val)[2:])

            print('#' * 50)
            print('Merge Files ...')
            print('#' * 50)
            # finally dsp bin file
            bin_merge_dsp = open('./templates/files/bin_merge_dsp.bin', 'ab')

            # part #1
            dsp_bin_file_flag = ''.join('{:02X}'.format(1))
            print('File flag(hex):' + str(dsp_bin_file_flag) + ', ' +
                  str(int(('0x' + str(dsp_bin_file_flag)), 16)))

            dsp_file_len_1 = addition + dsp_file_len

            dsp_bin_file_totallen = ''.join('{:08X}'.format(dsp_file_len_1))
            print('File Len(hex):' + str(dsp_bin_file_totallen) + ', ' +
                  str(int(('0x' + str(dsp_bin_file_totallen)), 16)))

            dsp_bin_file_crc = ''.join('{:08X}'.format(crc_val))
            print('File CRC(hex):' + str(dsp_bin_file_crc))

            dsp_bin_version = ''.join('{:08X}'.format( dsp_version ))

            # hex(i)[2::].decode('hex')[::-1].encode('hex')
            dsp_bin_file_head = ''.join('{:0486X}'.format(0))

            bin_merge_dsp.write(bytearray.fromhex(dsp_bin_file_flag))
            bin_merge_dsp.write(bytearray.fromhex(dsp_bin_file_totallen))
            bin_merge_dsp.write(bytearray.fromhex(dsp_bin_file_crc))
            bin_merge_dsp.write(bytearray.fromhex(dsp_bin_version))
            bin_merge_dsp.write(bytearray.fromhex(dsp_bin_file_head))
            bin_merge_dsp.write(dsp_bin)

            if addition != 0:
                print('add addition ...')
                f_str = '{:0' + str(addition * 2) + 'X}'
                dsp_file_len_4 = ''.join(f_str.format(0))
                bin_merge_dsp.write(bytearray.fromhex(dsp_file_len_4))


            bin_merge_dsp.close()

            # second pre-process, add crc to file tail, begin ...
            print("second pre-process, add crc to file tail, begin ...")
            with open('./templates/files/bin_merge_dsp.bin', "rb") as f:
                bin_file = f.read()

            bin_merge_dsp = open('./templates/files/bin_merge_dsp.bin', 'ab')
            crc_val = crc.main(bin_file)
            bin_file_crc = ''.join('{:08X}'.format(crc_val))
            print('The second pre-process whole File CRC(hex):' + str(bin_file_crc))
            dsp_bin_file_pad = ''.join('{:0504X}'.format(0))
            bin_merge_dsp.write(bytearray.fromhex(dsp_bin_file_pad))
            bin_merge_dsp.write(bytearray.fromhex(bin_file_crc))
            bin_merge_dsp.close()
            # second pre-process end ...

            # clean tmp files
            # os.system("del *.bin")

            print('#' * 50)
            print('FINALLY FILE: bin_merge_dsp.bin')
            print('#' * 50)
            # End preprocess =================================================================
            file_name = 'bin_merge_dsp.bin'
        else:
            start_addr = 65536 + 41 * 65536
            loop_count = 21

            # step1. erase flash
            a.write_item_to_config_ini('dev', 'module_firmware_file',
                                       file_name)

        # ---------------------------------------------------------
        print("starting to erase flash ...")
        for i in range(0, loop_count):
            # addr = 65536 + i * 65536
            addr = start_addr + i * 65536
            print("erase addr: " + hex(addr))
            s1.send(('*flash -b ' + str(addr)).encode())
            buffer_string = s1.recv(512)
            time.sleep(1)

        if file_type == 'dsp':
            s1.send('*dl 3 1'.encode())
        else:
            s1.send('*dl 4 1'.encode())

        # print(parse_cmdstr(buffer_string))
        buffer_string = s1.recv(512)
        if parse_cmdstr(buffer_string) == '$0000':
            # if True:
            print('erase ok!')
            # step2 download dsp bin file
            # ------------------------------------------------------
            # s2 = socket(AF_INET, SOCK_STREAM)
            s2 = socket()
            s2.connect((IP_ADDR, 1080))
            # init_data = tcp_client_socket.recv(1024)
            # print(init_data.decode('gbk'))
            epoch = time.time()
            f = open('./templates/files/' + file_name, 'rb')
            block = 1
            time.sleep(2)
            try:
                while True:
                    chunk = f.read(256)
                    if not chunk:
                        break
                    # do_something_with(chunk)
                    print("block: #" + str(block) + "\tdownloading: " +
                          str(len(chunk)))
                    s2.send(chunk)
                    recv = s2.recv(1024)
                    print(recv.decode('gbk'))
                    block += 1
                    time.sleep(0.085)
            finally:
                f.close()

            s2.close()
            print(file_type +
                  ' download time: {:.3f} s'.format(time.time() - epoch))

            if file_type == 'dsp':
                s1.send('*dl 3 2'.encode())
            else:
                s1.send('*dl 4 2'.encode())

            # Start to move data ===========================================================
            if move_data_flag == 1:
                # f.seek(0, os.SEEK_END)
                # size = f.tell()
                # f.seek(0)
                PROGRAM_FRAME_SIZE = 2048
                START_SECTOR = 0
                broker = Broker()
                broker.TWI_SPEED = 1000
                broker.twi_sbw(122, b'\xa5\x5a\x5a\xa5')

                flash = Flash(broker)

                file_name = 'bin_merge_dsp.bin'

                with open('./templates/files/' + file_name, 'rb') as dsp1:
                    dsp_bin = dsp1.read()

                size = len(dsp_bin)
                # size += Flash.PAGE_SIZE
                sector_count = size // Flash.SECTOR_SIZE
                if size % Flash.SECTOR_SIZE:
                    sector_count += 1
                page_count = size // Flash.PAGE_SIZE
                if size % Flash.PAGE_SIZE:
                    page_count += 1

                print('Now start to move data to module ...')
                epoch = time.time()
                for s in range(sector_count):
                    sys.stdout.write(
                        'Erasing sector {}...'.format(s + START_SECTOR))
                    sys.stdout.flush()
                    flash.erase_sector(s + START_SECTOR)
                    sys.stdout.write('done.\n')
                print('Erase Time: {:.3f} s'.format(time.time() - epoch))

                # address = START_SECTOR * Flash.SECTOR_SIZE
                # data = struct.pack('<I', size)
                # print('header page data {}...'.format(size))
                # flash.program(address, data)
                # count = flash.read(address, 4)
                # print('count %d.\n' % count)

                epoch = time.time()
                if 0:
                    # if count != ''.join(format(b, '02x') for b in struct.pack('<I', size)):
                    #     print('Could not program header sector.')
                    pass
                else:
                    address = 0x10000  #Host board store DSP area start
                    mcu_f_addr = START_SECTOR * Flash.SECTOR_SIZE
                    remaining = size
                    # for page in range(1, page_count + 1):
                    while remaining:
                        count = PROGRAM_FRAME_SIZE
                        if remaining < PROGRAM_FRAME_SIZE:
                            count = remaining

                        while not broker.cdb1_idle():
                            time.sleep(0.05)
                            pass
                        #switch page to a0
                        change_page_cmd = bytearray(b'\x00\xa0')
                        broker.twi_sbw(126, change_page_cmd)
                        time.sleep(0.03)
                        #tell host download bin to module
                        broker.dcpy(address, count)
                        time.sleep(0.05)

                        # while not broker.cdb1_idle():
                        #     time.sleep(0.05)
                        #     pass
                        #trig flash write ddb cmd
                        broker.twi_sbw(126, b'\x00\x9f')  #switch to page 0x9f
                        time.sleep(0.03)
                        cmd = bytearray(
                            b'\x80\x00\x00\x00\x07\x00\x00\x00\x0f\x06\x04\x00\x00\x00\x00'
                        )
                        cmd[-4] = (mcu_f_addr >> 24) & 0xff
                        cmd[-3] = (mcu_f_addr >> 16) & 0xff
                        cmd[-2] = (mcu_f_addr >> 8) & 0xff
                        cmd[-1] = mcu_f_addr & 0xff
                        # if length > 2048:
                        #     return 0
                        cmd[2] = (count >> 8) & 0xff  #EPL MSB
                        cmd[3] = count & 0xff  #EPL LSB
                        cmd[133 - 128] = broker.cdb_chkcode(cmd)
                        broker.twi_sbw(130, cmd[2:])
                        broker.twi_sbw(128, cmd[:2])
                        time.sleep(0.2)
                        while broker.cdb1_cip():
                            time.sleep(0.1)
                            pass

                        if broker.cdb1_success():
                            F = 'Programming Address: {:#010X} Count: {}'
                            print(F.format(address, count))
                            address += count
                            mcu_f_addr += count
                            remaining -= count
                            time.sleep(0.02)
                        else:
                            F = 'Error!! Programming Address: {:#010X} Count: {}'
                            print(F.format(address, count))
                            pass
                print('Programming Time: {:.3f} s'.format(time.time() - epoch))
                # Start to move data ===========================================================


            if file_type == 'dsp':
                s1.send('*dl 3 3'.encode())
                buffer_string = s1.recv(512)
                if parse_cmdstr(buffer_string) == '$0000':
                    return ('Download completely and flash data verify successful.')
            else:
                pass
        else:
            print('erase failed')

        return ('Download completely. ')

    if file_type == 'module_firmware_dsp':
        s1 = socket()
        s1.connect((IP_ADDR, 1000))
        s1.recv(512)

        a.write_item_to_config_ini('dev', 'module_firmware_file', file_name)
        # start_addr = 65536
        # loop_count = 41
        # # ---------------------------------------------------------
        # print("starting to erase flash ...")
        # for i in range(0, loop_count):
        #     # addr = 65536 + i * 65536
        #     addr = start_addr + i * 65536
        #     print("erase addr: " + hex(addr))
        #     s1.send(('*flash -b ' + str(addr)).encode())
        #     buffer_string = s1.recv(512)
        #     time.sleep(1)

        # s1.send('*dl 3 1'.encode())

        # # print(parse_cmdstr(buffer_string))
        # buffer_string = s1.recv(512)
        # if parse_cmdstr(buffer_string) == '$0000':
        #     # if True:
        #     print('erase ok!')
        #     # step2 download dsp bin file
        #     # ------------------------------------------------------
        #     # s2 = socket(AF_INET, SOCK_STREAM)
        #     s2 = socket()
        #     s2.connect((IP_ADDR, 1080))
        #     # init_data = tcp_client_socket.recv(1024)
        #     # print(init_data.decode('gbk'))
        #     epoch = time.time()
        #     f = open('./templates/files/' + file_name, 'rb')
        #     time.sleep(2)
        #     block = 1
        #     try:
        #         while True:
        #             chunk = f.read(256)
        #             if not chunk:
        #                 break
        #             # do_something_with(chunk)
        #             print("block: #" + str(block) + "\tdownloading: " +
        #                   str(len(chunk)))
        #             s2.send(chunk)
        #             recv = s2.recv(1024)
        #             print(recv.decode('gbk'))
        #             block += 1
        #             time.sleep(0.085)
        #     finally:
        #         f.close()

        #     s2.close()
        #     print(file_type +
        #           ' download time: {:.3f} s'.format(time.time() - epoch))

        #     s1.send('*dl 3 2'.encode())
        # else:
        #     print('erase failed')

        return ('The file has been submitted. Next, download to the module. ')

    # if GUI is customer version
    # module_config_table, cmis_config_table use bin  type, and download to module directly!!
    if for_customer == 'hide': #for customer
        # download config files, do not through host flash, dl directly!
        if file_type == 'module_config_table' or file_type == 'cmis_config_table':
            _broker = Broker()
            _broker.cdb_psw()
            cdb = CDB(_broker)
            # params_file = sys.argv[1]
            params_file = './templates/files/' + file_name

            with open(params_file, 'rb') as f:
                data = f.read(64)

                fileType = data[0]

                # if arguments.startandDL:
                if True:
                    epoch = time.time()
                    sys.stdout.write('Start Firmware Download...\n')
                    sys.stdout.flush()
                    res = cdb.CMD0101h(bytearray(data))
                    if 0x1 == res:
                        print('download start succeed.\n')
                        print('{:.3f} s'.format(time.time() - epoch))
                        BLOCK_SIZE = 2048
                        address = 0
                        # fileSize = os.path.getsize(arguments.bin)
                        fileSize = os.path.getsize(params_file)
                        remaining = fileSize - 64
                        print(remaining)
                        startTime = time.time()
                        # for sector in range(sector_count):
                        while remaining > 0:
                            count = BLOCK_SIZE
                            if remaining < BLOCK_SIZE:
                                count = remaining
                            data = f.read(count)
                            # print(data)
                            epoch = time.time()
                            F = 'Writing Firmware Image Address: {:#08x} length: {} '
                            sys.stdout.write(F.format(address, count))
                            sys.stdout.flush()
                            # cdb.CMD0104h_host(address, data)
                            if 0x80 == fileType:# fw
                                print('dl host flash data.\n')
                                cdb.CMD0104h_host(address, data)# download data on host flash
                            elif 0x82 == fileType:#fw+dsp
                                print('dl host flash data, fw+dsp.\n')
                                cdb.CMD0104h_host_fwdsp(address, data)
                            else:
                                print('dl file directly.\n')
                                cdb.CMD0104h(address, data)#do not through host flash, dl directly
                            print('{:.3f} s'.format(time.time() - epoch))

                            address += count
                            remaining -= count
                        print('{:.3f} s'.format(time.time() - startTime))
                    else:
                        print('download start failed.\n')
                        print(res)
                        print('{:.3f} s'.format(time.time() - epoch))

            print("start verify ...")
            sys.stdout.flush()
            res = cdb.CMD0107h()
            if 0x1 == res:
                v_str = "verify succeed."
                print('complete  verify succeed.\n')
            else:
                v_str = "verify failed."
                print('complete  verify failed.\n')
                print(res)                
            _broker.twi_bw(64, 1)   

            # print("Send complete\r\n")
            return ('Download completely, ' + v_str)
    else: # for insider
        if file_type == 'itla_firmware':
            print('itla_firmware ...')
            os.system("clean.bat")
            
            b = Broker()
            cdb = CDB(b)
            irst = DPin(b, "ITLA_OIF_RST_N")
            itla = Laser(b)
            b.cdb_psw()
            irst.state=1
            time.sleep(1)
            itla.baud=115200

            # params_file = sys.argv[1]
            params_file = './templates/files/' + file_name
            with open(params_file, 'rb') as f:
                ifw_raw_bin = f.read()

            rawLen = len(ifw_raw_bin)
            if (rawLen % 2) == 1:
                ifw_raw_bin += b'\xff'
                rawLen += 1
            print(rawLen)


            ifw_crc = crc.main(ifw_raw_bin)
            print(ifw_crc)

            fw_bin_reserved = ''.join('{:094X}'.format( 0 ))
            fw_bin_reserved1 = ''.join('{:008X}'.format( 0 ))

            ifw_bin = open('./templates/files/itla_fw_packed.bin', 'ab')

            ifw_bin.write(b'\x12')#bin type
            ifw_bin.write(struct.pack('>I', rawLen))
            ifw_bin.write(struct.pack('>I', ifw_crc))
            ifw_bin.write(bytearray.fromhex(fw_bin_reserved))
            ifw_bin.write(bytearray.fromhex(fw_bin_reserved1))
            ifw_bin.write(struct.pack('B', ord('N')))
            ifw_bin.write(struct.pack('B', ord('P')))
            ifw_bin.write(struct.pack('B', ord('T')))
            ifw_bin.write(struct.pack('B', ord('N')))
            ifw_bin.write(ifw_raw_bin)

            ifw_bin.close()

            b.twi_sbw(122, b'\x00\x00\x10\x11')
            with open('./templates/files/itla_fw_packed.bin', 'rb') as f:
                data = f.read(64)
                print(data)
                fileType = data[0]

                epoch = time.time()
                sys.stdout.write('Start Firmware Download...\n')
                sys.stdout.flush()
                res = cdb.CMD0101h(bytearray(data))
                if 0x1 == res:#write EPL
                    print('download start succeed.\n')
                    print('{:.3f} s'.format(time.time() - epoch))
                    BLOCK_SIZE = 2048#768#2048
                    address = 0
                    fileSize = os.path.getsize('./templates/files/itla_fw_packed.bin')
                    remaining = fileSize - 64
                    print(remaining)
                    startTime = time.time()
                    while remaining > 0:
                        count = BLOCK_SIZE
                        if remaining < BLOCK_SIZE:
                            count = remaining
                        data = f.read(count)
                        epoch = time.time()
                        F = 'Writing Firmware Image Address: {:#08x} length: {} '
                        sys.stdout.write(F.format(address, count))
                        sys.stdout.flush()
                        print('dl ap.\n')
                        cdb.CMD0104h_AP(address, data)
                        print('{:.3f} s'.format(time.time() - epoch))
                        address += count
                        remaining -= count
                    print('{:.3f} s'.format(time.time() - startTime))

                    #veriry part
                    epoch = time.time()
                    sys.stdout.write('Firmware Download Complete: ')
                    sys.stdout.flush()
                    res = cdb.CMD0107h()
                    print('{:.3f} s'.format(time.time() - epoch))

                    irst.state=0
                    print('Pull down ITLA_RST_N.\n')
                    time.sleep(2)
                    irst.state=1
                    print('Pull up ITLA_RST_N.\n')
                    time.sleep(1)
                    itla.baud=9600

                    if 0x1 == res:
                        print('complete  verify succeed.\n')
                        return ('Download completely.')
                    else:
                        print('complete  verify failed.\n')
                        print(res)  
                        return ('Download completely, ' + str(res))
                else:
                    irst.state=0
                    print('Pull down ITLA_RST_N.\n')
                    time.sleep(2)
                    irst.state=1
                    print('Pull up ITLA_RST_N.\n')
                    time.sleep(1)
                    itla.baud=9600
                    
                    print('download start failed.\n')
                    print(res)
                    print('{:.3f} s'.format(time.time() - epoch))     
                    return ('Download completely, ' + str(res))

                
        if file_type == 'module_config_table':
            _broker = Broker()
            _broker.cdb_psw()
            flash = Flash(_broker)

            # params_file = sys.argv[1]
            params_file = './templates/files/' + file_name

            wb = load_workbook(filename=params_file, data_only=True)

            ver_byte_arr = b''
            ver_sheet = wb['Sheet1']
            # ver_byte_arr += struct.pack('B', int(ver_sheet['I2'].value))#little endian
            # ver_byte_arr += struct.pack('B', int(ver_sheet['H2'].value))
            try:
                ver_byte_arr += struct.pack('B', int(
                    ver_sheet['I2'].value))  #little endian
                ver_byte_arr += struct.pack('B', int(ver_sheet['H2'].value))
            except:
                ver_byte_arr += struct.pack('B', 0)  #little endian
                ver_byte_arr += struct.pack('B', 0)

            # DSP sheet Start
            dsp_sheet = wb['DSP']

            dsp_byte_arr = b''
            for i in dsp_sheet['E']:
                if (None != i.value) and ('Target Value' != i.value):
                    if i.value < 0x80000000:
                        dsp_byte_arr += struct.pack('<i', int(i.value))
                    else:
                        dsp_byte_arr += struct.pack('<I', int(i.value))
                        print(i.value)

            print(dsp_byte_arr)

            print('dsp2_byte_arr ...')
            dsp2_byte_arr = b''
            try:
                dsp_sheet = wb['DSP2']
                for i in dsp_sheet['E']:
                    if(None != i.value) and ('Target Value' != i.value):
                        if i.value < 0x80000000:
                            dsp2_byte_arr += struct.pack('<i', int(i.value))
                        else:
                            dsp2_byte_arr += struct.pack('<I', int(i.value))
                            # print(i.value)
            except:
                print('Skip DSP2 Sheet...')
            print(dsp2_byte_arr)

            print('dsp3_to_8_byte_arr ...')
            dsp3_to_8_byte_arr = b''
            for sheet_item in ['DSP3','DSP4','DSP5','DSP6','DSP7','DSP8' ]:
                try:
                    dsp_sheet = wb[sheet_item]
                    for i in dsp_sheet['E']:
                        if(None != i.value) and ('Target Value' != i.value):
                            if i.value < 0x80000000:
                                dsp3_to_8_byte_arr += struct.pack('<i', int(i.value))
                            else:
                                dsp3_to_8_byte_arr += struct.pack('<I', int(i.value))
                                # print(i.value)
                except:
                    print('Skip ' + sheet_item + ' Sheet...')
            print(dsp3_to_8_byte_arr)

            dac_byte_arr = b''
            dac_sheet = wb['DAC']
            for i in dac_sheet['E']:
                if (None != i.value) and ('Translate Val' != i.value):
                    print(i.value)
                    dac_byte_arr += struct.pack('<I', int(i.value))
                    print(i.value)
            print(dac_byte_arr)

            ddm_byte_arr = b''
            ddm_sheet = wb['DDM']
            for i in ddm_sheet['C']:
                if (None != i.value) and ('Target Value' != i.value):
                    ddm_byte_arr += struct.pack('<f', float(i.value))
            print(ddm_byte_arr)

            ctrl_byte_arr = b''
            try:
                ctrl_sheet = wb['CTRL']
                for i in ctrl_sheet['C']:
                    if (None != i.value) and ('En/Dis' != i.value):
                        # print(i.value)
                        # ctrl_byte_arr += struct.pack('<i', int(i.value))
                        if i.value < 0x80000000:
                            ctrl_byte_arr += struct.pack('<i', int(i.value))
                        else:
                            ctrl_byte_arr += struct.pack('<I', int(i.value))

                print('ctrl_byte_arr')
                print(ctrl_byte_arr)
            except KeyError:
                print("skip CTRL sheet ...")

            biaskb_byte_arr = b''
            try:
                biaskb_sheet = wb['BiasKB']
                for i in biaskb_sheet['C']:
                    if(None != i.value):
                        # print(i.value)
                        biaskb_byte_arr += struct.pack('<f', float(i.value))
                print('biaskb_byte_arr')
                print(biaskb_byte_arr)
            except KeyError:
                print("skip BiasKB sheet ...")

            abc_byte_arr = b''
            try:
                abc_sheet = wb['ABC']
                
                for row in abc_sheet.iter_rows():
                    if row[1].value is None or row[2].value is None:
                        continue
                    else:
                        print(row[1].value,'<---->',row[2].value)
                        abc_byte_arr += struct.pack( row[1].value, row[2].value)
                    
                print('abc_byte_arr')
                print(abc_byte_arr)
            except:
                print('Skip ABC Sheet...')

            osnr_byte_arr = b''
            try:
                osnr_sheet = wb['OSNR']
                
                for row in osnr_sheet.iter_rows():
                    if row[1].value is None or row[2].value is None:
                        continue
                    else:
                        print(row[1].value,'<---->',row[2].value)
                        osnr_byte_arr += struct.pack( row[1].value, row[2].value)
                    
                print('osnr_byte_arr')
                print(osnr_byte_arr)
            except:
                print('Skip OSNR Sheet...')


            supplemental_byte_arr = b''
            supplemental_byte_arr_tmp = b''
            try:
                supplemental_sheet = wb['Supplemental']

                for row in supplemental_sheet.iter_rows():
                    if row[1].value is None or row[2].value is None:
                        continue
                    else:
                        print(row[1].value,'<---->',row[2].value)
                        supplemental_byte_arr_tmp += struct.pack( row[1].value, row[2].value)

                print('supplemental_byte_arr length:', len(supplemental_byte_arr_tmp))
                print(struct.pack('<I', len(supplemental_byte_arr_tmp)))
                
                supplemental_byte_arr = struct.pack('<I', len(supplemental_byte_arr_tmp)) + supplemental_byte_arr_tmp
                print(supplemental_byte_arr)
            except:
                print('Skip Supplemental Sheet...')


            data = dsp_byte_arr + dsp2_byte_arr + dsp3_to_8_byte_arr + dac_byte_arr + ddm_byte_arr + ctrl_byte_arr + biaskb_byte_arr + abc_byte_arr  + osnr_byte_arr + supplemental_byte_arr
            # print(data)
            crcVal = crc.main(data)
            length = len(data)
            reserved = ''.join('{:0106X}'.format(0))  # fill 53 bytes 0

            if PRODUCT == 'OSFP':
                data = b'\x10' + \
                       struct.pack('<I', length) + \
                       struct.pack('<I', crcVal) + \
                       ver_byte_arr + \
                       bytearray.fromhex(reserved) + \
                       dsp_byte_arr + \
                       dsp2_byte_arr + \
                       dsp3_to_8_byte_arr + \
                       dac_byte_arr + \
                       ddm_byte_arr + \
                       ctrl_byte_arr + \
                       biaskb_byte_arr + \
                       abc_byte_arr + \
                       osnr_byte_arr + \
                       supplemental_byte_arr
            else:  #QSFP-DD
                data = b'\x90' + \
                       struct.pack('<I', length) + \
                       struct.pack('<I', crcVal) + \
                       ver_byte_arr + \
                       bytearray.fromhex(reserved) + \
                       dsp_byte_arr + \
                       dsp2_byte_arr + \
                       dsp3_to_8_byte_arr + \
                       dac_byte_arr + \
                       ddm_byte_arr + \
                       ctrl_byte_arr + \
                       biaskb_byte_arr + \
                       abc_byte_arr + \
                       osnr_byte_arr + \
                       supplemental_byte_arr

            print(data)

            startAddr = 0x300000
            sectorNo = int(startAddr / 4096)
            i = 0
            while i < 4:
                flash.erase_sector(sectorNo + i)
                i += 1
            remaining = len(data)
            sended = 0
            BLOCK_SIZE = 128
            while remaining:
                if remaining >= BLOCK_SIZE:
                    flash.program(startAddr + sended,
                                  data[sended:(sended + BLOCK_SIZE)])
                    sended += BLOCK_SIZE
                    remaining -= BLOCK_SIZE
                else:
                    flash.program(startAddr + sended, data[sended:])
                    sended += remaining
                    remaining -= remaining

            # verify start!
            verify_str = str(flash.cfg_verify())

            # if verify ok, module config filename save to config.ini
            if flash.cfg_verify() == 90:
                a.write_item_to_config_ini('dev', 'module_config_file', file_name)

            # download HW info table
            try:
                ver_byte_arr = b''
                ver_sheet = wb['HW_INFO_VER']
                ver_byte_arr += struct.pack('<I', int(ver_sheet['F2'].value,16))#little endian

                # HW_INFO
                hw_info_sheet = wb['HW_INFO']

                hw_info_byte_arr = b''
                for i in hw_info_sheet['E']:
                    if(None != i.value) and ('Target Value' != i.value):
                        hw_info_byte_arr += struct.pack('<I', int(i.value))
                        print(i.value)
                
                # print(hw_info_byte_arr)

                data = hw_info_byte_arr
                # print(data)
                crcVal = crc.main(data)
                length = len(data)
                # reserved = ''.join('{:0110X}'.format( 0 ))#fill 55 bytes 0
                data = b'\x14\x08\x20\x20' + \
                        ver_byte_arr + \
                       struct.pack('<I', length) + \
                       struct.pack('<I', crcVal) + \
                       hw_info_byte_arr
            
                print(data)
                a.write_item_to_config_ini('dev', 'module_config_file_len', str(len(data)))

                startAddr = 0x308000
                sectorNo = int(startAddr / 4096)
                i = 0
                while i < 1:
                    flash.erase_sector(sectorNo + i)
                    i += 1
                remaining = len(data)
                sended = 0
                BLOCK_SIZE = 128
                while remaining:
                    if remaining >= BLOCK_SIZE:
                        flash.program(startAddr+sended, data[sended:(sended+BLOCK_SIZE)])
                        sended += BLOCK_SIZE
                        remaining -= BLOCK_SIZE
                    else:
                        flash.program(startAddr+sended, data[sended:])
                        sended += remaining
                        remaining -= remaining

                print("Send complete\r\n")
                # start verify ---------------------------------------------------------------------------
                # params_file = sys.argv[1]
                params_file = './templates/files/' + file_name
                print("Start verify ...", params_file)
                wb = load_workbook(filename = params_file, data_only = True)

                ver_byte_arr = b''
                ver_sheet = wb['HW_INFO_VER']
                ver_byte_arr += struct.pack('<I', int(ver_sheet['F2'].value, 16))#little endian

                # HW_INFO
                hw_info_sheet = wb['HW_INFO']

                hw_info_byte_arr = b''
                for i in hw_info_sheet['E']:
                    if(None != i.value) and ('Target Value' != i.value):
                        hw_info_byte_arr += struct.pack('<I', int(i.value))
                        print(i.value)
                
                # print(hw_info_byte_arr)

                data = hw_info_byte_arr
                # print(data)
                crcVal = crc.main(data)
                length = len(data)
                # reserved = ''.join('{:0110X}'.format( 0 ))#fill 55 bytes 0
                data = b'\x14\x08\x20\x20' + \
                        ver_byte_arr + \
                       struct.pack('<I', length) + \
                       struct.pack('<I', crcVal) + \
                       hw_info_byte_arr
                       
                print(data)

                startAddr = 0x308000
                sectorNo = int(startAddr / 4096)

                readRes = b''
                remaining = len(data)
                readout = 0
                BLOCK_SIZE = 128
                while remaining:
                    if remaining >= BLOCK_SIZE:
                        res = flash.read(startAddr+readout, BLOCK_SIZE)
                        readRes += struct.pack('%sB'%len(res), *res)
                        readout += BLOCK_SIZE
                        remaining -= BLOCK_SIZE
                    else:
                        res = flash.read(startAddr+readout, remaining)
                        readRes += struct.pack('%sB'%len(res), *res)
                        readout += remaining
                        remaining -= remaining
                print(readRes)

                flash_data = ''.join(['%04X ' %x  for x in readRes])
                print("DATA: {}".format(flash_data))


                if readRes == data:
                    print("HW info table verfiy success\r\n")
                    ret = 'HW info table verfiy success.'
                else:
                    print("HW info table verfiy failed\r\n")
                    ret = 'HW info table verfiy failed.'

                # return ('Download completely ' + ret)
                # print("Send complete\r\n")
                # return ('Download completely, ' + verify_str + '.') 
            except KeyError:
                print("skip HW_INFO sheet ...")        

            # print("Send complete\r\n")
            return ('Download completely, ' + verify_str + '.')
        if file_type == 'cmis_config_table':
            _broker = Broker()
            _broker.cdb_psw()
            flash = Flash(_broker)

            # params_file = sys.argv[1]
            params_file = './templates/files/' + file_name

            # need test and verify!!!! 2022-12-30
            cols = [1]
            wb1 = load_workbook(params_file, data_only=True)
            wb = wb1['Summary']

            for col_idx in range(wb.max_column-2):
                if (col_idx == 0 or col_idx == 1 or col_idx == 2):
                    continue
                
                if wb.cell(row=3, column=col_idx+1).value == 'FF':
                    #print('break!')
                    break
                else:
                    #print(wb.cell(row=3, column=col_idx+1).value)
                    cols.append(col_idx)

            print(cols)

            summary_byte_arr = b''
            # for col in [
            #         1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
            #         20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 
            #         36, 37, 38, 39, 40, 41, 42, 43, 44, 45
            # ]:
            for col in cols:   
                pdata = pd.read_excel(params_file,
                                      sheet_name="Summary",
                                      usecols=[col])
                pdata = pdata.dropna(how='any')
                #print(data)

                for index, row in pdata.iterrows():
                    if 'Low' in str(row[0]) or 'Page' in str(row[0]):
                        continue

                    print(int(str(row[0]), 16))
                    summary_byte_arr += struct.pack('<B', int(str(row[0]), 16))

            # print(summary_byte_arr)
            ####################################################################
            # fileType 0x11, flash start addr: 0x304000.
            data = summary_byte_arr
            print(data)
            crcVal = crc.main(data)
            length = len(data)
            reserved = ''.join('{:0110X}'.format(0))  #fill 55 bytes 0
            if PRODUCT == 'OSFP':
                data = b'\x11' + \
                       struct.pack('<I', length) + \
                       struct.pack('<I', crcVal) + \
                       bytearray.fromhex(reserved) + \
                       summary_byte_arr
            else:  # QSFP-DD
                data = b'\x91' + \
                       struct.pack('<I', length) + \
                       struct.pack('<I', crcVal) + \
                       bytearray.fromhex(reserved) + \
                       summary_byte_arr

            print(data)

            startAddr = 0x304000
            sectorNo = int(startAddr / 4096)
            i = 0
            while i < 4:
                flash.erase_sector(sectorNo + i)
                i += 1
            remaining = len(data)
            sended = 0
            BLOCK_SIZE = 128
            while remaining:
                if remaining >= BLOCK_SIZE:
                    flash.program(startAddr + sended,
                                  data[sended:(sended + BLOCK_SIZE)])
                    sended += BLOCK_SIZE
                    remaining -= BLOCK_SIZE
                else:
                    flash.program(startAddr + sended, data[sended:])
                    sended += remaining
                    remaining -= remaining

            # verify start!
            verify_str = ''
            # verify_str = str(flash.cfg_verify())
            # print("Send complete\r\n")
            return ('Download completely, ' + verify_str + '.')

    return ('OK')


@download_bp.route('/api/only_move_data')
def only_move_data():
    setdefaulttimeout(200000)
    # "MCU_MOD_SELN" , 56
    a.dout_set(56, 0)

    if True:
        # f.seek(0, os.SEEK_END)
        # size = f.tell()
        # f.seek(0)
        PROGRAM_FRAME_SIZE = 2048
        # PROGRAM_FRAME_SIZE = 128
        START_SECTOR = 0
        broker = Broker()
        broker.TWI_SPEED = 1000
        broker.twi_sbw(122, b'\xa5\x5a\x5a\xa5')

        flash = Flash(broker)

        file_name = 'bin_merge_dsp.bin'

        with open('./templates/files/' + file_name, 'rb') as dsp1:
            dsp_bin = dsp1.read()

        size = len(dsp_bin)
        print('size=' + str(size))
        # size += Flash.PAGE_SIZE
        sector_count = size // Flash.SECTOR_SIZE
        if size % Flash.SECTOR_SIZE:
            sector_count += 1
        page_count = size // Flash.PAGE_SIZE
        if size % Flash.PAGE_SIZE:
            page_count += 1

        print('Now start to move data to module ...')
        epoch = time.time()
        for s in range(sector_count):
            sys.stdout.write('Erasing sector {}...'.format(s + START_SECTOR))
            sys.stdout.flush()
            flash.erase_sector(s + START_SECTOR)
            sys.stdout.write('done.\n')
        print('Erase Time: {:.3f} s'.format(time.time() - epoch))

        # address = START_SECTOR * Flash.SECTOR_SIZE
        # data = struct.pack('<I', size)
        # print('header page data {}...'.format(size))
        # flash.program(address, data)
        # count = flash.read(address, 4)
        # print('count %d.\n' % count)

        epoch = time.time()
        if 0:
            # if count != ''.join(format(b, '02x') for b in struct.pack('<I', size)):
            #     print('Could not program header sector.')
            pass
        else:
            address = 0x10000  #Host board store DSP area start
            mcu_f_addr = START_SECTOR * Flash.SECTOR_SIZE
            remaining = size
            # for page in range(1, page_count + 1):
            while remaining:
                count = PROGRAM_FRAME_SIZE
                if remaining < PROGRAM_FRAME_SIZE:
                    count = remaining

                while not broker.cdb1_idle():
                    time.sleep(0.05)
                    pass
                #switch page to a0
                change_page_cmd = bytearray(b'\x00\xa0')
                broker.twi_sbw(126, change_page_cmd)
                time.sleep(0.03)
                #tell host download bin to module
                broker.dcpy(address, count)
                time.sleep(0.05)

                # while not broker.cdb1_idle():
                #     time.sleep(0.05)
                #     pass
                #trig flash write ddb cmd
                broker.twi_sbw(126, b'\x00\x9f')  #switch to page 0x9f
                time.sleep(0.03)
                cmd = bytearray(
                    b'\x80\x00\x00\x00\x07\x00\x00\x00\x0f\x06\x04\x00\x00\x00\x00'
                )
                cmd[-4] = (mcu_f_addr >> 24) & 0xff
                cmd[-3] = (mcu_f_addr >> 16) & 0xff
                cmd[-2] = (mcu_f_addr >> 8) & 0xff
                cmd[-1] = mcu_f_addr & 0xff
                # if length > 2048:
                #     return 0
                cmd[2] = (count >> 8) & 0xff  #EPL MSB
                cmd[3] = count & 0xff  #EPL LSB
                cmd[133 - 128] = broker.cdb_chkcode(cmd)
                broker.twi_sbw(130, cmd[2:])
                broker.twi_sbw(128, cmd[:2])
                time.sleep(0.2)
                while broker.cdb1_cip():
                    time.sleep(0.1)
                    pass

                if broker.cdb1_success():
                    F = 'Programming Address: {:#010X} Count: {}'
                    print(F.format(address, count))
                    address += count
                    mcu_f_addr += count
                    remaining -= count
                    time.sleep(0.02)
                else:
                    F = 'Error!! Programming Address: {:#010X} Count: {}'
                    print(F.format(address, count))
                    pass
        print('Programming Time: {:.3f} s'.format(time.time() - epoch))
        return "ok"


@download_bp.route('/api/download_module_firmware')
def download_module_firmware():
    setdefaulttimeout(200000)
    module_firmware_file = a.read_item_from_config_ini('dev',
                                                       'module_firmware_file')
    print(module_firmware_file)
    b = Broker()
    # b.IP = arguments.portal
    cdb = CDB(b)

    b.twi_sbw(122, b'\x00\x00\x10\x11')
    # with open(arguments.bin, 'rb') as f:
    with open('./templates/files/' + module_firmware_file, 'rb') as f:
        data = f.read(64)
        print(data)
        fileType = data[0]

        # if arguments.startandDL:
        if True:
            epoch = time.time()
            sys.stdout.write('Start Firmware Download...\n')
            sys.stdout.flush()
            res = cdb.CMD0101h(bytearray(data))
            if 0x1 == res:
                print('download start succeed.\n')
                print('{:.3f} s'.format(time.time() - epoch))
                BLOCK_SIZE = 2048#768#2048
                address = 0
                # fileSize = os.path.getsize(arguments.bin)
                fileSize = os.path.getsize('./templates/files/' + module_firmware_file)
                remaining = fileSize - 64
                print(remaining)
                startTime = time.time()
                # for sector in range(sector_count):
                while remaining > 0:
                    count = BLOCK_SIZE
                    if remaining < BLOCK_SIZE:
                        count = remaining
                    data = f.read(count)
                    # print(data)
                    epoch = time.time()
                    F = 'Writing Firmware Image Address: {:#08x} length: {} '
                    sys.stdout.write(F.format(address, count))
                    sys.stdout.flush()
                    # cdb.CMD0104h_host(address, data)
                    # if 0 == fileType:# fw
                    #     print('dl ap.\n')
                    #     # cdb.CMD0104h_host(address, data)# download data on host flash
                    #     # cdb.CMD0104h_host_fwdsp(address, data)
                    #     cdb.CMD0104h_AP(address, data)
                    # elif 2 == fileType:#fw+dsp
                    #     print('dl host flash data, fw+dsp.\n')
                    print('dl ap.\n')
                    #     # cdb.CMD0104h_host_fwdsp(address, data)
                    #     # cdb.CMD0104h(address, data)#do not through host flash, dl directly
                    cdb.CMD0104h_AP(address, data)
                    # else:
                    #     print('dl file directly.\n')
                        # cdb.CMD0104h(address, data)#do not through host flash, dl directly
                    print('{:.3f} s'.format(time.time() - epoch))

                    address += count
                    remaining -= count
                print('{:.3f} s'.format(time.time() - startTime))
            else:
                print('download start failed.\n')
                print(res)
                print('{:.3f} s'.format(time.time() - epoch))

    # verify bin file
    b.twi_sbw(122, b'\x00\x00\x10\x11')
    epoch = time.time()
    sys.stdout.write('Firmware Download Complete: ')
    sys.stdout.flush()
    res = cdb.CMD0107h()
    print('{:.3f} s'.format(time.time() - epoch))
    if 0x1 == res:
        print('complete  verify succeed.\n')
        return "ok"
    else:
        print('complete  verify failed.\n')
        print(res)   
        return "notok"         



@download_bp.route('/api/run_module_firmware')
def run_module_firmware():
    setdefaulttimeout(200000)
    b = Broker()
    cdb = CDB(b)
    b.twi_sbw(122, b'\x00\x00\x10\x11')
    epoch = time.time()
    sys.stdout.write('Run Other Image...')
    cdb.CMD0109h()
    print('{:.3f} s'.format(time.time() - epoch))
    time.sleep(3)
    return "ok"


@download_bp.route('/api/commit_module_firmware')
def commit_module_firmware():
    setdefaulttimeout(200000)
    b = Broker()
    cdb = CDB(b)
    b.twi_sbw(122, b'\x00\x00\x10\x11')
    epoch = time.time()
    sys.stdout.write('Committing Downloaded Image...')
    cdb.CMD010Ah()
    print('{:.3f} s'.format(time.time() - epoch))
    return "ok"


@download_bp.route('/api/copy_module_firmware')
def copy_module_firmware():
    setdefaulttimeout(200000)
    b = Broker()
    cdb = CDB(b)
    b.twi_sbw(122, b'\x00\x00\x10\x11')
    epoch = time.time()
    sys.stdout.write('Copy Image...')
    rlplen,rlp_chkcode,rlp = cdb.CMD0108h(0)
    if b.cdb_chkcode(rlp) == rlp_chkcode:
        sys.stdout.write('Copied bytes is %d\n' % (struct.unpack('>I', rlp[0:4])[0]))#bit0
        sys.stdout.write('Direction is 0x%2x\n' % rlp[4])
        sys.stdout.write('copy failed %d\n' % rlp[5])
    print('{:.3f} s'.format(time.time() - epoch))
    return "ok"


# @download_bp.route('/api/verify_module_file', methods=['GET', 'POST'])
# def verify_module_file():
#     setdefaulttimeout(200000)
#     file_type = request.form["file_type"]
#     verify_flag = True

#     module_firmware_file = a.read_item_from_config_ini('dev', 'module_firmware_file')
#     f = open('./templates/files/' + module_firmware_file, 'rb')
#     addr = -8

#     IP_ADDR = a.read_item_from_config_ini('dev', 'ip')
#     s1 = socket()
#     s1.connect((IP_ADDR, 1000))
#     s1.recv(512)
#     t1 = time.time()

#     if file_type == "module_firmware":
#         # module_firmware: 0x2A0000
#         print("Starting verify module_firmware ...")
#         start_address = 2752512
#     else:
#         # module_firmware_dsp: 0x10000
#         print("Starting verify module_firmware_dsp ...")
#         start_address = 65536

#     try:
#         while True:
#             chunk = f.read(8)
#             if not chunk:
#                 break

#             addr = addr + 8
#             # do_something_with(chunk)
#             s1.send(('*flash -r ' + hex(start_address + addr) + ' 8').encode())
#             buffer_string = s1.recv(512)
#             # print(parse_ret(buffer_string))
#             a1 = parse_ret(buffer_string).split(',')
#             a2 = []
#             for i in a1:
#                 a2.append(int('0x' + i, 16))

#             flash = bytes(a2)
#             if chunk == flash[0:len(chunk)]:
#                 file_data = ''.join(['%04X ' %x  for x in chunk])
#                 print("VERIFY: OK!  ADDRESS: {}  DATA: {}".format(hex(start_address + addr).upper(), file_data))
#             else:
#                 file_data = ''.join(['%04X ' %x  for x in chunk])
#                 flash_data = ''.join(['%04X ' %x  for x in flash])
#                 print("FAILED!  ADDRESS: {}  FILE_DATA: {}  FLASH_DATA: {}".format(hex(start_address + addr).upper(), file_data, flash_data))
#                 verify_flag = False
#                 break
#     finally:
#         f.close()

#     if verify_flag:
#         print("ALL DATA VERIFY OK!")
#         print("Spend ", time.time()-t1, " S.")
#         return "ok"
#     else:
#         print("DATA VERIFY FAILED!")
#         print("Spend ", time.time()-t1, " S.")
#         return "not ok"



@download_bp.route('/api/drc_module_firmware')
def drc_module_firmware():
    download_module_firmware()
    run_module_firmware()
    commit_module_firmware()

    copy_image = request.args.get('copy_image')
    if int(copy_image) == 1:
        print('Copy firmware image. Image A and Image B will be upgraded automatically...')
        copy_module_firmware()

    return 'ok'
    
    # # download ----------------------------------------------------------------
    # setdefaulttimeout(200000)
    # module_firmware_file = a.read_item_from_config_ini('dev',
    #                                                    'module_firmware_file')
    # print(module_firmware_file)
    # # with open(arguments.bin, 'rb') as f:
    # with open('./templates/files/' + module_firmware_file, 'rb') as f:
    #     data = f.read(64)
    #     print(data)
    #     fileType = data[0]

    #     abc_len = struct.unpack('>I', data[1:5])[0]
    #     abc_crc = struct.unpack('>I', data[5:9])[0]
    #     main_len = struct.unpack('>I', data[9:13])[0]
    #     main_crc = struct.unpack('>I', data[13:17])[0]

    #     print('abc_len %08X.\n' % abc_len)
    #     print('abc_crc %08X.\n' % abc_crc)
    #     print('main_len %08X.\n' % main_len)
    #     print('main_crc %08X.\n' % main_crc)

    #     # Start ----------------------------------------------------
    #     b = Broker()
    #     cdb = CDB(b)
    #     b.twi_bw(64, 0)  # disable event log
    #     epoch = time.time()
    #     print('Start Firmware Download...\n')
    #     try_count = 0
    #     start_ret = True
    #     while True:
    #         try_count = try_count + 1
    #         res = cdb.CMD0101h(bytearray(data))
    #         if 0x1 == res:
    #             print('download start succeed.\n')
    #             break
    #         else:
    #             print(res)
    #             time.sleep(0.01)
    #             if try_count > 10:
    #                 start_ret = False
    #                 break
    #     if start_ret is False:
    #         return "download start failed."

    #     print('{:.3f} s'.format(time.time() - epoch))
    #     # Download ---------------------------------------------------------
    #     BLOCK_SIZE = 2048
    #     address = 0
    #     # remaining = main_len + abc_len
    #     fileSize = os.path.getsize('./templates/files/' + module_firmware_file)
    #     remaining = fileSize - 64

    #     print(remaining)
    #     startTime = time.time()
    #     # for sector in range(sector_count):
    #     while remaining > 0:
    #         count = BLOCK_SIZE
    #         if remaining < BLOCK_SIZE:
    #             count = remaining
    #         data = f.read(count)

    #         epoch = time.time()
    #         F = 'Writing Firmware Image Address: {:#08x} length: {} '
    #         sys.stdout.write(F.format(address, count))
    #         sys.stdout.flush()
    #         # cdb.CMD0104h_host(address, data)
    #         if 0 == fileType or 0x80 == fileType:  # fw
    #             # if 0 == fileType:  # fw
    #             print('dl host flash data.\n')
    #             cdb.CMD0104h_host(address, data)  # download data on host flash
    #         elif 2 == fileType or 0x82 == fileType:  #fw+dsp
    #             # elif 2 == fileType:  #fw+dsp
    #             print('dl host flash data, fw+dsp.\n')
    #             cdb.CMD0104h_host_fwdsp(address, data)
    #         else:
    #             print('dl file directly.\n')
    #             cdb.CMD0104h(address,
    #                          data)  #do not through host flash, dl directly

    #         print('{:.3f} s'.format(time.time() - epoch))

    #         address += count
    #         remaining -= count
    #     print('{:.3f} s'.format(time.time() - startTime))
    #     # Verify ------------------------------------------------------------
    #     epoch = time.time()
    #     sys.stdout.write('Firmware Download Complete: ')
    #     sys.stdout.flush()
    #     # res = cdb.CMD0107h()
    #     # print('{:.3f} s'.format(time.time() - epoch))
    #     try_count = 0
    #     verify_ret = True
    #     while True:
    #         try_count = try_count + 1
    #         res = cdb.CMD0107h()
    #         if 0x1 == res:
    #             print('complete  verify succeed.\n')
    #             break
    #         else:
    #             print(res)
    #             time.sleep(0.01)
    #             if try_count > 10:
    #                 verify_ret = False
    #                 break
    #     print('{:.3f} s'.format(time.time() - epoch))
    #     if verify_ret is False:
    #         return "complete  verify failed.\n"
    #     b.twi_bw(64, 1)
    # # run ----------------------------------------------------------------
    # epoch = time.time()
    # sys.stdout.write('Run Other Image...')
    # cdb.CMD0109h()
    # print('{:.3f} s'.format(time.time() - epoch))
    # time.sleep(3)
    # # commit ----------------------------------------------------------------
    # print("Committing ...")
    # epoch = time.time()
    # sys.stdout.write('Committing Downloaded Image...')
    # cdb.CMD010Ah()
    # print('{:.3f} s'.format(time.time() - epoch))
    # return "ok"


@download_bp.route('/api/mct_file_upload', methods=['POST'])
def mct_file_upload():
    setdefaulttimeout(200000)
    file = request.files.get("mct_file")
    if file is None:
        # return "error, file is null."
        return '...'

    file_name = file.filename
    print(file_name)
    file.save('./templates/files/' + file_name)
    a.write_item_to_config_ini('dev', 'module_config_file', file_name)

    print('Uploaded successfully')
    return 'Uploaded successfully.'
